#include "stdafx.h"
#include "Exception.h"
#include "utf8.h"
#include "utf8string.h"

namespace ja2
{
	std::wstring to_utf16(std::string const &Str)
	{
		std::wstring out;
		try
		{
			utf8::utf8to16(Str.begin(), Str.end(), std::back_inserter(out));
		}
		catch(utf8::invalid_utf8 const &e)
		{
			throw InvalidUtf8((boost::format("%1%: %X") % e.what() % e.utf8_octet()).str());
		}

		return out;
	}

	std::string to_utf8(std::wstring const &Str)
	{
		std::string out;
		utf8::utf16to8(Str.begin(), Str.end(), std::back_inserter(out));
		return out;
	}
} /*ja2*/
/*
namespace _StrCmp
{
	////////////////////////////////////////////////////////////////
	inline void Advance( const char*& s1, const char*& s2 )
	{
		while (*s1 && *s2 && toupper(*s1) == toupper(*s2))
		{
			++s1;
			++s2;
		}
	}
	inline void Advance( const wchar_t*& s1, const wchar_t*& s2 )
	{
		// should be 'towupper'
		while (*s1 && *s2 && toupper(*s1) == toupper(*s2))
		{
			++s1;
			++s2;
		}	
	}
	template<typename CharType>
	inline void AdvanceCase( const CharType*& s1, const CharType*& s2 )
	{
		while (*s1 && *s2 && (*s1 == *s2))
		{
			++s1;
			++s2;
		}	
	}
	////////////////////////////////////////////////////////////////
	template<typename CharType>
	inline bool Equal( const CharType* s1, const CharType* s2 )
	{
		return !(*s1 || *s2);
	}
	////////////////////////////////////////////////////////////////
	inline bool Less( const wchar_t* s1, const wchar_t* s2 )
	{
		if (!*s1) return *s2 != 0;
		if (!*s2) return false;
		// should be 'towupper'
		return toupper(*s1) < toupper(*s2);
	}
	inline bool Less( const char* s1, const char* s2 )
	{
		if (!*s1) return *s2 != 0;
		if (!*s2) return false;
		return toupper(*s1) < toupper(*s2);
	}
	template<typename CharType>
	inline bool LessCase( const CharType* s1, const CharType* s2 )
	{
		if (!*s1) return *s2 != 0;
		if (!*s2) return false;
		return (*s1) < (*s2);
	}
}

bool utf8string::lessCase(const utf8string::char_t* s1, const utf8string::char_t* s2)
{
	_StrCmp::AdvanceCase(s1,s2);
	return _StrCmp::LessCase(s1,s2);

}

bool utf8string::less(const utf8string::char_t* s1, const utf8string::char_t* s2)
{
	_StrCmp::Advance(s1,s2);
	return _StrCmp::Less(s1,s2);
}

bool utf8string::equalCase(const utf8string::char_t* s1, const utf8string::char_t* s2)
{
	_StrCmp::AdvanceCase(s1,s2);
	return _StrCmp::Equal(s1,s2);
}

bool utf8string::equal(const utf8string::char_t* s1, const utf8string::char_t* s2)
{
	_StrCmp::Advance(s1,s2);
	return _StrCmp::Equal(s1,s2);
}
*/

/*
utf8string::size_t utf8string::narrow(std::wstring const& src, std::string& dst)
{
	utf8string::size_t len = utf8string::narrow(src.c_str(),src.length(),NULL,0);
	dst.resize(len);
	return utf8string::narrow(src.c_str(),src.length(),&dst[0],len);
}
std::string utf8string::narrow(wchar_t const* str, utf8string::size_t length)
{
	utf8string::size_t len = utf8string::narrow(str,length,NULL,0);
	std::string s;
	s.resize(len);
	utf8string::narrow(str,length,&s[0],len);
	return s;
}
utf8string::size_t utf8string::narrow(wchar_t const* src_str, utf8string::size_t src_len, char* dst_str, utf8string::size_t dst_len)
{
	if(src_str && src_len>0)
	{
		if(!dst_str || dst_len==0)
		{
			return wcstombs(NULL, src_str, src_len);
		}
		return wcstombs(dst_str, src_str, std::min<utf8string::size_t>(src_len,dst_len));
	}
	return 0;
}
// 
std::wstring utf8string::widen(char const* str, utf8string::size_t length)
{
	utf8string::size_t len = utf8string::widen(str,length,NULL,0);
	std::wstring ws;
	ws.resize(len);
	utf8string::widen(str,length,&ws[0],len);
	return ws;
}
utf8string::size_t utf8string::widen(std::string const& src, std::wstring& dst)
{
	utf8string::size_t len = utf8string::widen(src.c_str(),src.length(),NULL,0);
	dst.resize(len);
	return utf8string::widen(src.c_str(),src.length(),&dst[0],len);
}
utf8string::size_t utf8string::widen(char const* src_str, size_t src_len, wchar_t* dst_str, size_t dst_len)
{
	if(src_str && src_len>0)
	{
		if(!dst_str || dst_len==0)
		{
			return mbstowcs(NULL, src_str, src_len);
		}
		return mbstowcs(dst_str, src_str, std::min<size_t>(src_len,dst_len));
	}
	return 0;
}
*/

/*
bool operator<(utf8string const& s1, utf8string const& s2)
{
	return s1.m_Str < s2.m_Str;
}

std::wstringstream& operator<<(std::wstringstream& out, utf8string const& str)
{
	out.write(str.c_str(), (std::streamsize)str.length());
	return out;
}

std::wstringstream& operator<<(std::wstringstream& out, utf8string::str_t const& str)
{
	out.write(str.c_str(), (std::streamsize)str.length());
	return out;
}

std::wstringstream& operator<<(std::wstringstream& out, const utf8string::char_t* str)
{
	out.write(str, (std::streamsize)wcslen(str));
	return out;
}
*/
/*
// case IN-sensitive
bool StrCmp::Equal(const char* s1, const char* s2)
{
	_StrCmp::Advance(s1,s2);
	return _StrCmp::Equal(s1,s2);
}
bool StrCmp::Equal(std::string const& s1, std::string const& s2)
{
	const char* p1 = s1.c_str();
	const char* p2 = s2.c_str();
	_StrCmp::Advance(p1,p2);
	return _StrCmp::Equal(p1,p2);
}
bool StrCmp::Equal(std::string const& s1, const char* s2)
{
	const char* p1 = s1.c_str();
	_StrCmp::Advance(p1,s2);
	return _StrCmp::Equal(p1,s2);
}
bool StrCmp::Equal(const char* s1, std::string const& s2)
{
	const char* p2 = s2.c_str();
	_StrCmp::Advance(s1,p2);
	return _StrCmp::Equal(s1,p2);
}
//
bool StrCmp::Equal(const wchar_t* s1, const wchar_t* s2)
{
	_StrCmp::Advance(s1,s2);
	return _StrCmp::Equal(s1,s2);
}
bool StrCmp::Equal(std::wstring const& s1, std::wstring const& s2)
{
	const wchar_t* p1 = s1.c_str();
	const wchar_t* p2 = s2.c_str();
	_StrCmp::Advance(p1,p2);
	return _StrCmp::Equal(p1,p2);
}
bool StrCmp::Equal(std::wstring const& s1, const wchar_t* s2)
{
	const wchar_t* p1 = s1.c_str();
	_StrCmp::Advance(p1,s2);
	return _StrCmp::Equal(p1,s2);
}
bool StrCmp::Equal(const wchar_t* s1, std::wstring const& s2)
{
	const wchar_t* p2 = s2.c_str();
	_StrCmp::Advance(s1,p2);
	return _StrCmp::Equal(s1,p2);
}
//
bool StrCmp::Equal(utf8string const& s1, utf8string const& s2)
{
	const wchar_t* p1 = s1.c_str();
	const wchar_t* p2 = s2.c_str();
	_StrCmp::Advance(p1,p2);
	return _StrCmp::Equal(p1,p2);
}
bool StrCmp::Equal(utf8string const& s1, std::wstring const& s2)
{
	const wchar_t* p1 = s1.c_str();
	const wchar_t* p2 = s2.c_str();
	_StrCmp::Advance(p1,p2);
	return _StrCmp::Equal(p1,p2);
}
bool StrCmp::Equal(std::wstring const& s1, utf8string const& s2)
{
	const wchar_t* p1 = s1.c_str();
	const wchar_t* p2 = s2.c_str();
	_StrCmp::Advance(p1,p2);
	return _StrCmp::Equal(p1,p2);
}
bool StrCmp::Equal(utf8string const& s1, const wchar_t* s2)
{
	const wchar_t* p1 = s1.c_str();
	_StrCmp::Advance(p1,s2);
	return _StrCmp::Equal(p1,s2);
}
bool StrCmp::Equal(const wchar_t* s1, utf8string const& s2)
{
	const wchar_t* p2 = s2.c_str();
	_StrCmp::Advance(s1,p2);
	return _StrCmp::Equal(s1,p2);
}
// case Sensitive
bool StrCmp::EqualCase(const char* s1, const char* s2)
{
	_StrCmp::AdvanceCase(s1,s2);
	return _StrCmp::Equal(s1,s2);
}
bool StrCmp::EqualCase(std::string const& s1, std::string const& s2)
{
	const char* p1 = s1.c_str();
	const char* p2 = s2.c_str();
	_StrCmp::AdvanceCase(p1,p2);
	return _StrCmp::Equal(p1,p2);
}
bool StrCmp::EqualCase(std::string const& s1, const char* s2)
{
	const char* p1 = s1.c_str();
	_StrCmp::AdvanceCase(p1,s2);
	return _StrCmp::Equal(p1,s2);
}
bool StrCmp::EqualCase(const char* s1, std::string const& s2)
{
	const char* p2 = s2.c_str();
	_StrCmp::AdvanceCase(s1,p2);
	return _StrCmp::Equal(s1,p2);
}
//
bool StrCmp::EqualCase(const wchar_t* s1, const wchar_t* s2)
{
	_StrCmp::AdvanceCase(s1,s2);
	return _StrCmp::Equal(s1,s2);
}
bool StrCmp::EqualCase(std::wstring const& s1, std::wstring const& s2)
{
	const wchar_t* p1 = s1.c_str();
	const wchar_t* p2 = s2.c_str();
	_StrCmp::AdvanceCase(p1,p2);
	return _StrCmp::Equal(p1,p2);
}
bool StrCmp::EqualCase(std::wstring const& s1, const wchar_t* s2)
{
	const wchar_t* p1 = s1.c_str();
	_StrCmp::AdvanceCase(p1,s2);
	return _StrCmp::Equal(p1,s2);
}
bool StrCmp::EqualCase(const wchar_t* s1, std::wstring const& s2)
{
	const wchar_t* p2 = s2.c_str();
	_StrCmp::AdvanceCase(s1,p2);
	return _StrCmp::Equal(s1,p2);
}
//
bool StrCmp::EqualCase(utf8string const& s1, utf8string const& s2)
{
	const wchar_t* p1 = s1.c_str();
	const wchar_t* p2 = s2.c_str();
	_StrCmp::AdvanceCase(p1,p2);
	return _StrCmp::Equal(p1,p2);
}
bool StrCmp::EqualCase(utf8string const& s1, std::wstring const& s2)
{
	const wchar_t* p1 = s1.c_str();
	const wchar_t* p2 = s2.c_str();
	_StrCmp::AdvanceCase(p1,p2);
	return _StrCmp::Equal(p1,p2);
}
bool StrCmp::EqualCase(std::wstring const& s1, utf8string const& s2)
{
	const wchar_t* p1 = s1.c_str();
	const wchar_t* p2 = s2.c_str();
	_StrCmp::AdvanceCase(p1,p2);
	return _StrCmp::Equal(p1,p2);
}
bool StrCmp::EqualCase(utf8string const& s1, const wchar_t* s2)
{
	const wchar_t* p1 = s1.c_str();
	_StrCmp::AdvanceCase(p1,s2);
	return _StrCmp::Equal(p1,s2);
}
bool StrCmp::EqualCase(const wchar_t* s1, utf8string const& s2)
{
	const wchar_t* p2 = s2.c_str();
	_StrCmp::AdvanceCase(s1,p2);
	return _StrCmp::Equal(s1,p2);
}
*/